import scrapy
import json
from ..items import CarScrapyItem
import time
import random
from fake_headers import Headers


class GuaziSpider(scrapy.Spider):
    name = 'GuaziSpider'
    allowed_domains = ['guazi.com']

    # header = {
    #     ":authority": "mapi.guazi.com",
    #     ":method": "GET",
    #     ":path": "/car-source/carList/pcList?minor=&sourceType=&ec_buy_car_list_ab=&location_city=&district_id=&tag=-1&license_date=&auto_type=&driving_type=&gearbox=&road_haul=&air_displacement=&emission=&car_color=&guobie=&bright_spot_config=&seat=&fuel_type=&order=&priceRange=0,-1&tag_types=18&diff_city=&intention_options=&initialPriceRange=&monthlyPriceRange=&transfer_num=&car_year=&carid_qigangshu=&carid_jinqixingshi=&cheliangjibie=&page=1&pageSize=20&city_filter=123&city=123&guazi_city=123&qpres=&versionId=0.0.0.0&osv=IOS&platfromSource=wap",
    #     ":scheme": "https",
    #     "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
    #     "accept-encoding": "gzip, deflate, br",
    #     "accept-language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
    #     "cache-control": "max-age=0",
    #     "cookie": "uuid=e6dec57f-b71b-4bd0-c771-6073d2437c47; cainfo=%7B%22ca_s%22%3A%22self%22%2C%22ca_n%22%3A%22self%22%2C%22ca_medium%22%3A%22-%22%2C%22ca_term%22%3A%22-%22%2C%22ca_content%22%3A%22-%22%2C%22ca_campaign%22%3A%22-%22%2C%22ca_kw%22%3A%22-%22%2C%22ca_i%22%3A%22-%22%2C%22scode%22%3A%22-%22%2C%22guid%22%3A%22e6dec57f-b71b-4bd0-c771-6073d2437c47%22%7D; sessionid=6c93d473-1408-4514-bcf7-31773843fe78",
    #     "sec-ch-ua": '"Google Chrome";v="95", "Chromium";v="95", ";Not A Brand";v="99"',
    #     "sec-ch-ua-mobile": "?0",
    #     "sec-ch-ua-platform": "macOS",
    #     "sec-fetch-dest": "document",
    #     "sec-fetch-mode": "navigate",
    #     "sec-fetch-site": "none",
    #     "sec-fetch-user": "?1",
    #     "upgrade-insecure-requests": "1",
    #     "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36"
    # }
    # use fake header

    header = Headers(
        browser="chrome",  # Generate only Chrome UA
        os="mac",  # Generate ony Windows platform
        headers=True  # generate misc headers
    )

    font0_num_map = {
        "&#59854;": "0",
        "&#58397;": "1",
        "&#58928;": "2",
        "&#60146;": "3",
        "&#58149;": "4",
        "&#59537;": "5",
        "&#60492;": "6",
        "&#57808;": "7",
        "&#59246;": "8",
        "&#58670;": "9"
    }

    font1_num_map = {
        "&#59854;": "0",
        "&#58670;": "1",
        "&#59246;": "2",
        "&#59537;": "3",
        "&#57808;": "4",
        "&#60146;": "5",
        "&#60492;": "6",
        "&#58149;": "7",
        "&#58928;": "8",
        "&#58397;": "9"
    }

    font2_num_map = {
        "&#59854;": "0",
        "&#58397;": "1",
        "&#58670;": "2",
        "&#58928;": "3",
        "&#60492;": "4",
        "&#59246;": "5",
        "&#57808;": "6",
        "&#60146;": "7",
        "&#59537;": "8",
        "&#58149;": "9"
    }

    font3_num_map = {
        '&#59854;': '0',
        '&#59537;': '1',
        '&#58149;': '2',
        '&#58397;': '3',
        '&#58670;': '4',
        '&#58928;': '5',
        '&#60492;': '6',
        '&#59246;': '7',
        '&#57808;': '8',
        '&#60146;': '9'
    }

    font4_num_map = {
        "&#59854;": "0",
        "&#59246;": "1",
        "&#57808;": "2",
        "&#60146;": "3",
        "&#59537;": "4",
        "&#58149;": "5",
        "&#58397;": "6",
        "&#58670;": "7",
        "&#58928;": "8",
        "&#60492;": "9"
    }

    fonts_num_map_list = [font0_num_map, font1_num_map, font2_num_map, font3_num_map, font4_num_map]

    def start_requests(self):
        for page in range(1, 81):
            url_format = 'https://mapi.guazi.com/car-source/carList/pcList?minor=&sourceType=&ec_buy_car_list_ab=&location_city=&district_id=&tag=-1&license_date=&auto_type=&driving_type=&gearbox=&road_haul=&air_displacement=&emission=&car_color=&guobie=&bright_spot_config=&seat=&fuel_type=&order=&priceRange=0,-1&tag_types=18&diff_city=&intention_options=&initialPriceRange=&monthlyPriceRange=&transfer_num=&car_year=&carid_qigangshu=&carid_jinqixingshi=&cheliangjibie=&page={}&pageSize=20&city_filter=123&city=123&guazi_city=123&qpres=&versionId=0.0.0.0&osv=IOS&platfromSource=wap'
            time.sleep(random.randint(1, 4))
            yield scrapy.Request(url=url_format.format(page), headers=self.header.generate(), callback=self.page_parse)

    # 使用5套 字体编码->数字 映射表 解析爬取的数据
    def decode_num(self, text: str, font_num_mp):
        result = text
        for key in font_num_mp:
            result = result.replace(key, font_num_mp[key])
        return result

    def decode_num_by_maps(self, text):
        res_list = []
        for font_num_map in self.fonts_num_map_list:
            result = self.decode_num(text, font_num_map)
            res_list.append(result)
        return res_list

    # 计算最优的字体编码映射
    # 计算规则：
    # 1、首付价格<一口价<收购价
    # 2、首付价格/一口价 ～= 30% 三层首付
    def cal_best_font_map_index(self, price_list, first_pay_list, buyOutPrice):
        # 设置一个很大的收车价
        buyPrice = 10000000000
        # 有些车型收购价数据为空
        if "" != buyOutPrice:
            buyPrice = float(buyOutPrice.split("万")[0])
        # 共5个映射表 故准备5个索引
        list_index = [0, 1, 2, 3, 4]
        for i in range(5):
            # 有些车辆存在不支持首付的情况，故first_pay可能为空
            first_pay = 0
            if "" != first_pay_list[i]:
                first_pay = float(first_pay_list[i].split("万")[0])
            price = float(price_list[i].split("万")[0])
            # 计算首付比例 向下取整
            first_ratio = int(first_pay * 10 / price)
            if first_pay > price or price >= buyPrice or first_ratio != 3:
                list_index.remove(i)
        return list_index

    def page_parse(self, response):
        print(response.text)
        jsonObj = json.loads(response.text)
        for car in jsonObj['data']['postList']:
            carItem = CarScrapyItem()
            title = car['title']
            price = car['price']
            first_pay = car['first_pay']
            road_haul = car['road_haul']
            buyOutPrice = ''
            if 'buyOutPrice' in car:
                buyOutPrice = car['buyOutPrice']
            license_date = car['license_date']
            carItem['title'] = title
            price_list = self.decode_num_by_maps(price)
            carItem['price0'] = price_list[0]
            carItem['price1'] = price_list[1]
            carItem['price2'] = price_list[2]
            carItem['price3'] = price_list[3]
            carItem['price4'] = price_list[4]
            first_pay_list = self.decode_num_by_maps(first_pay)
            carItem['first_pay0'] = first_pay_list[0]
            carItem['first_pay1'] = first_pay_list[1]
            carItem['first_pay2'] = first_pay_list[2]
            carItem['first_pay3'] = first_pay_list[3]
            carItem['first_pay4'] = first_pay_list[4]
            road_haul_list = self.decode_num_by_maps(road_haul)
            carItem['road_haul0'] = road_haul_list[0]
            carItem['road_haul1'] = road_haul_list[1]
            carItem['road_haul2'] = road_haul_list[2]
            carItem['road_haul3'] = road_haul_list[3]
            carItem['road_haul4'] = road_haul_list[4]
            carItem['buyOutPrice'] = buyOutPrice
            carItem['license_date'] = license_date
            try:
                best_index = self.cal_best_font_map_index(price_list, first_pay_list, buyOutPrice)[0]
            except ValueError as e:
                print("#" * 50)
                print(e, car)
                print("#" * 50)
                continue
            # 不符合价格规则，跳过此车辆
            except IndexError as e:
                print("#" * 50)
                print(e, car)
                print(price_list)
                print(first_pay_list)
                print(buyOutPrice)
                print("#" * 50)
                continue

            best_price = price_list[best_index]
            best_first_pay = first_pay_list[best_index]
            best_road_haul = road_haul_list[best_index]

            carItem['best_price'] = best_price
            carItem['best_first_pay'] = best_first_pay
            carItem['best_road_haul'] = best_road_haul
            carItem['best_index'] = best_index

            yield carItem
